/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package rallyracer;

import au.com.bytecode.opencsv.CSVWriter;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map.Entry;
import java.util.TreeMap;
import java.util.TreeSet;
import org.joda.time.DateTime;

/**
 *
 * @author samra_000
 */
public class Segment  implements Comparator<Segment>
{
    private final TreeMap<Integer, DataPoint> dataPoints;
    private DateTime absoluteStartTime;
    private final int segmentNumber;
    
    public Segment( int segmentNubmer )
    {
        this.dataPoints = Maps.newTreeMap();
        this.absoluteStartTime = null;
        this.segmentNumber = segmentNubmer;
    }
    
    public int getSegmentNumber()
    {
        return this.segmentNumber;
    }
    
    public void add( DataPoint p ) throws DuplicateDataPointInSegmentException
    {
        if( this.dataPoints.containsKey(p.serialNumber) )
        {
            throw new DuplicateDataPointInSegmentException("Duplicate DataPoint Added", this, this.dataPoints.get(p.serialNumber), p);
        }
        this.dataPoints.put(p.serialNumber, p);
        System.out.println( p.toString() );
    }
    
    public List<DataPoint> getDataPoints()
    {
        return new ArrayList<>(this.dataPoints.values());
    }
    
    public DataPoint getDataPointAt( int index )
    {
        return this.dataPoints.get(index);
    }
    
    public float getRecommendedSpeedAt( int index )
    {
        int stPoint = index;
        while(stPoint > 0 && (this.getDataPointAt(stPoint)==null || this.getDataPointAt(stPoint).recommendedSpeed < 0))
        {
            stPoint--;
        }
        return this.getDataPointAt(stPoint).recommendedSpeed;
    }
    
    public void setAbsoluteStartTime(DateTime dateTime)
    {
        this.absoluteStartTime = dateTime;
    }
    
    public DateTime getAbsoluteStartTime()
    {
        return this.absoluteStartTime;
    }
    
    public void compute(DateTime startTime)
    {
        List<DataPoint> dataPoints =  this.getDataPoints();
        float currentRecommendedSpeed = -1;
        
        for(int i=0; i<dataPoints.size(); i++)
        {
            DataPoint dataPoint = dataPoints.get(i);
            
            if( dataPoint.recommendedSpeed == -1 && currentRecommendedSpeed == -1)
            {
                //recommended speed & currentspeed unknown skipping
                continue;
            }
            else if( currentRecommendedSpeed == -1 )
            {
                currentRecommendedSpeed = dataPoint.recommendedSpeed;
                dataPoint.time=0;
                dataPoint.absoluteTime = startTime;
                continue;
            }
            
            //compute time to travel this segment
            DataPoint prevPoint = dataPoints.get(i-1);
            float deltaDistance = dataPoint.distanceFromStart - prevPoint.distanceFromStart;
            float timeTakenInSecs = deltaDistance*60f*60f/currentRecommendedSpeed;
            dataPoint.time = prevPoint.time + timeTakenInSecs;
            if(dataPoint.pause > 0 )
            {
                dataPoint.time += dataPoint.pause;
            }
            dataPoint.absoluteTime = startTime.plusSeconds(Math.round(dataPoint.time));
            
            // if change in recommended speed
            if( dataPoint.recommendedSpeed != -1 )
            {
                currentRecommendedSpeed = dataPoint.recommendedSpeed;
            }
        }
    }
    
    public void save() throws IOException
    {
        File file = new File("./segment-"+this.segmentNumber+".log");
        file.delete();
        file.createNewFile();
        
        try (CSVWriter writer = new CSVWriter(new FileWriter(file))) 
        {
            writer.writeNext(DataPoint.header);
            for(DataPoint p: this.getDataPoints())
            {
                writer.writeNext(p.getCSVContent());
            }
        }
    }

    @Override
    public int compare(Segment o1, Segment o2) 
    {
        return o1.segmentNumber - o2.segmentNumber;
    }
    
    @Override
    public String toString()
    {
        StringBuilder s = new StringBuilder();
        s.append("Segment: " + this.getSegmentNumber());
        for(DataPoint p: this.getDataPoints())
        {
            s.append("\n"+p);
        }
        return s.toString();
    }
    
}
